package com.citrinus.feedme;

import java.util.List;
import java.util.Random;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.renderscript.Type.CubemapFace;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.Gravity;
import android.webkit.WebChromeClient.CustomViewCallback;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
import com.citrinus.feedme.listener.MenuItemClickListener;
import com.citrinus.feedme.listener.PlacesUpdateListener;
import com.citrinus.feedme.listener.ShakeListener;
import com.citrinus.feedme.location.LocationChangeListener;
import com.citrinus.feedme.location.LocationHandler;
import com.citrinus.feedme.places.Place;
import com.citrinus.feedme.places.PlacesHandler;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.model.LatLng;

public class MainActivity extends SherlockFragmentActivity implements LocationChangeListener, PlacesUpdateListener, MenuItemClickListener, ShakeListener {

	private static final String TAG = MainActivity.class.getSimpleName();
	public final static int GOOGLEPLAY_REQUEST_CODE = 3;

	private LocationHandler locationHandler;
	private MenuFragment menuFragment;
	private MapFragment mapFragment;
	private DrawerLayout menuPane;
	private App app;
	private LatLng position;
	private int serverConnectionAttemps;
	private static final int MAX_ATTEMPS = 5;
	private ShakeDetection shakelistener;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// show spinner while loading background information
		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		setContentView(R.layout.activity_main);
		setSupportProgressBarIndeterminateVisibility(false);

		menuPane = (DrawerLayout) findViewById(R.id.drawer);

		// Build fragment objects
		mapFragment = (MapFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame);
		mapFragment.setCustomMessage(R.string.msg_no_position);

		menuFragment = (MenuFragment) getSupportFragmentManager().findFragmentById(R.id.menu);
		menuFragment.setMenuItemClickListener(this);
		// init location handler
		locationHandler = new LocationHandler(this);
		locationHandler.setListener(this);

		// set top bar
		app = (App) getApplication();
		app.setTopBar(this);

		// init shake listener for random selected restaurant
		shakelistener = new ShakeDetection(this);
		shakelistener.setListener(this);

	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if (requestCode == GOOGLEPLAY_REQUEST_CODE) {
			if (resultCode == Activity.RESULT_OK) {
				isGooglePlayServicesAvailable();
			} else {
				// No Google Services, no maps so finish
				finish();
			}
		}
	}

	@Override
	protected void onStart() {
		super.onStart();
	}

	@Override
	protected void onPause() {
		super.onPause();
		stopLocation();
		shakelistener.disableShakeListener();
	}

	@Override
	protected void onResume() {
		super.onResume();
		shakelistener.enableShakeListener();
		startLocation();		
	}

	@Override
	protected void onStop() {
		Log.v(TAG, "onStop");
		super.onStop();
		stopLocation();
	}

	@Override
	public void onDestroy() {
		Log.v(TAG, "onDestroy");
		super.onDestroy();
	}

	private boolean isGooglePlayServicesAvailable() {
		int code = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

		if (code == ConnectionResult.SUCCESS) {
			Log.i(TAG, "Google Play Services is available.");
			return true;
		} else {
			Log.w(TAG, "Google Play Services is unavailable, disabled or outdated.");
			GooglePlayServicesUtil.getErrorDialog(code, this, GOOGLEPLAY_REQUEST_CODE).show();
			return false;
		}
	}

	/**
	 * received new location
	 */
	@Override
	public void onLocationUpdateListener(LatLng position) {
		this.position = position;
		menuFragment.updateData(position);
		mapFragment.updateData(position);
		mapFragment.center(position);

		// center user in point
		Log.d(TAG, "new Location " + position.toString());
		stopLocation();
		// if network available, update places data
		if (locationHandler.isNetworkAvailable(this)) {
			updatePlacesData();
		}

		mapFragment.setCustomMessage(R.string.msg_shake);

	}

	@Override
	public void onPlacesUpdate(boolean isOK) {

		Log.d(TAG, "Received update");

		if (isOK) {
			menuFragment.updateData(position);
			mapFragment.updateData(position);
			setSupportProgressBarIndeterminateVisibility(false);
			serverConnectionAttemps = MAX_ATTEMPS;
		} else if (serverConnectionAttemps < MAX_ATTEMPS) {
			serverConnectionAttemps++;

			final PlacesHandler placesHandler = new PlacesHandler();
			placesHandler.setListener(this);

			new Thread(new Runnable() {

				@Override
				public void run() {
					try {
						Log.d(TAG, "Waiting...");
						Thread.sleep(5000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					placesHandler.execute(position);
					Log.d(TAG, "Trying again " + serverConnectionAttemps);
				}
			}).start();

		} else {
			setSupportProgressBarIndeterminateVisibility(false);
			Toast.makeText(this, getResources().getString(R.string.server_no_connection), Toast.LENGTH_LONG).show();
			mapFragment.setCustomMessage(R.string.server_no_connection);
		}

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getSupportMenuInflater().inflate(R.menu.topbar_menu, menu);
		return true;
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			toggleDrawer();
			break;
		case R.id.menu_center:
			// enable location sources
			locationHandler.isLocationEnable(this);
			if (position != null) {
				mapFragment.center(position);
				mapFragment.updateData(position);
			}
			startLocation();
			break;
		case R.id.menu_sync:

			// if network is available
			if (locationHandler.isNetworkAvailable(this)) {
				// but no position
				if (position == null) {
					// get position
					locationHandler.startLocationServices();
					mapFragment.setCustomMessage(R.string.msg_position_searching);
				} else {
					// if position and network available
					// get updated places
					updatePlacesData();
					mapFragment.setCustomMessage(R.string.msg_sync);
				}
			} else {
				// ask user to enable networking
				locationHandler.showNoInternetDialog(this);
			}

			break;
		}

		return super.onMenuItemSelected(featureId, item);
	}

	public void toggleDrawer() {
		if (menuPane.isDrawerOpen(Gravity.LEFT)) {
			menuPane.closeDrawer(Gravity.LEFT);
		} else {
			menuPane.openDrawer(Gravity.LEFT);
		}
	}

	private void startLocation() {
		boolean isConnected = locationHandler.startLocationServices();
		locationHandler.requestLocationUpdates();
		if (isConnected) {
			mapFragment.setCustomMessage(R.string.msg_position_searching);
		} else {
			mapFragment.setCustomMessage(R.string.msg_no_position);
			
		}

	}

	private void stopLocation() {
		locationHandler.stopLocationServices();
	}

	@Override
	public void menuItemClick(Place p) {
		menuPane.closeDrawer(Gravity.LEFT);
		mapFragment.centerInLocal(p);
	}

	@Override
	public void onShakeListener() {

		if (position != null) {
			List<Place> places = App.instance.getDb().getNearPlaces(position);

			int pi = 0;
			switch (places.size()) {
			case 0:
				mapFragment.setCustomMessage(R.string.restaurant_list_empty);
				return;
			case 1:
				pi = 0;
				break;
			default:
				Random r = new Random();
				pi = r.nextInt(places.size() - 1);
				break;
			}
			menuItemClick(places.get(pi));
			mapFragment.setCustomMessage(places.get(pi).getName());
		}
	}

	// update places data
	public void updatePlacesData() {
		serverConnectionAttemps = 0;
		PlacesHandler placesHandler = new PlacesHandler();
		placesHandler.setListener(this);
		placesHandler.execute(position);
		setSupportProgressBarIndeterminateVisibility(true);

	}

}
